package com.hmdp.utils;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;
@Component
public class DateIdGenerator {
    
    // 配置参数
    private static final int MAX_DAILY = 100000;          // 每天最大ID数
    private static final int PADDING_LENGTH = 6;         // 自增号长度（000001-100000）
    private static final int EXPIRE_DAYS = 7;            // Redis数据保留天数
    private static final String DATE_FORMAT = "yyyyMMdd";// 日期格式
    
    private final StringRedisTemplate redisTemplate;
    private final DateTimeFormatter dateFormatter;

    public DateIdGenerator(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
        this.dateFormatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
    }

    /**
     * 生成当日唯一ID
     * @return 格式：yyyyMMdd-000001
     * @throws DailyIdOverflowException 当日ID已耗尽时抛出
     */
    public String generate() {
        // 1. 获取当前日期
        String currentDate = LocalDate.now().format(dateFormatter);
        
        // 2. 构建Redis键
        String redisKey = "idgen:" + currentDate;
        
        // 3. 原子自增
        Long count = redisTemplate.opsForValue().increment(redisKey);
        if (count == null) {
            throw new RuntimeException("Redis操作失败");
        }
        
        // 4. 首次自增时设置过期时间
        if (count == 1) {
            redisTemplate.expire(redisKey, EXPIRE_DAYS, TimeUnit.DAYS);
        }
        
        // 5. 检查数量限制
        if (count > MAX_DAILY) {
            throw new DailyIdOverflowException(
                "当日[" + currentDate + "]ID已达上限" + MAX_DAILY);
        }
        
        // 6. 格式化输出
        return String.format("%s%s",
            currentDate,
            String.format("%0" + PADDING_LENGTH + "d", count));
    }

    // 自定义异常
    public static class DailyIdOverflowException extends RuntimeException {
        public DailyIdOverflowException(String message) {
            super(message);
        }
    }
}